// License Notification
//======================================================
// Copyright (c) 2010 Channel Intelligence Inc.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// ======================================================




using System.Diagnostics;

namespace CIP4.Simple
{
    public class WrapperStatsType
    {
        public enum StatsTypesEnum
        {
            Get,
            Save,
            Purge
        }

        public enum StatsCounterTypeEnum
        {
            Count,
            CountPerSec,
            AveragePerSec,
            AverageBase
        }

        public PerformanceCounter[][] Counters = new PerformanceCounter[][] {null, null, null};

        /// <summary>
        /// Total elapsed time spent getting items 
        /// </summary>
        public Stopwatch TotalGetTime { get; set; }

        /// <summary>
        /// Total elapsed time spent saving items 
        /// </summary>
        public Stopwatch TotalSaveTime { get; set; }

        /// <summary>
        /// Total elapsed time spent purging items 
        /// </summary>
        public Stopwatch TotalPurgeTime { get; set; }

        public WrapperStatsType()
        {
            TotalGetTime = new Stopwatch();
            TotalSaveTime = new Stopwatch();
            TotalPurgeTime = new Stopwatch();
            Initialize();
        }

        private void Initialize()
        {
            if (!PerformanceCounterCategory.Exists("CIP4Counters"))
            {
                CounterCreationDataCollection counters = new CounterCreationDataCollection();

                CreateCounter(StatsTypesEnum.Get, counters);

                CreateCounter(StatsTypesEnum.Save, counters);

                CreateCounter(StatsTypesEnum.Purge, counters);

                // create new category with the counters above

                PerformanceCounterCategory.Create(
                    "CIP4Counters",
                    "Counters for the CIP4 StrongWrapper interface", 
                    PerformanceCounterCategoryType.SingleInstance, 
                    counters);
            }

            GetCounter(StatsTypesEnum.Get);
            GetCounter(StatsTypesEnum.Purge);
            GetCounter(StatsTypesEnum.Save);
        }

        private void GetCounter(StatsTypesEnum name)
        {
            PerformanceCounter[] counters = new[] {
                new PerformanceCounter{
                    CategoryName = "CIP4Counters",
                    CounterName = string.Format("# {0}s executed", name),
                    MachineName = ".",
                    ReadOnly = false},

                new PerformanceCounter{
                    CategoryName = "CIP4Counters",
                    CounterName = string.Format("# {0}s / sec", name),
                    MachineName = ".",
                    ReadOnly = false},

                new PerformanceCounter{
                    CategoryName = "CIP4Counters",
                    CounterName = string.Format("average time per {0}", name),
                    MachineName = ".",
                    ReadOnly = false},

                new PerformanceCounter{
                    CategoryName = "CIP4Counters",
                    CounterName = string.Format("average time per {0} base", name),
                    MachineName = ".",
                    ReadOnly = false}
            };
            Counters[(int)name] = counters; 
        }

        private static void CreateCounter(StatsTypesEnum name, CounterCreationDataCollection counters)
        {
            // 1. counter for counting totals: PerformanceCounterType.NumberOfItems32

            CounterCreationData totalCount = 
                new CounterCreationData
                {
                    CounterName = string.Format("# {0}s executed", name),
                    CounterHelp = string.Format("Total number of {0}s executed", name),
                    CounterType = PerformanceCounterType.NumberOfItems32
                };
            counters.Add(totalCount);

            // 2. counter for counting operations per second:

            //        PerformanceCounterType.RateOfCountsPerSecond32

            CounterCreationData sPerSecond = 
                new CounterCreationData
                {
                    CounterName = string.Format("# {0}s / sec", name),
                    CounterHelp = string.Format("Number of {0}s executed per second", name),
                    CounterType = PerformanceCounterType.RateOfCountsPerSecond32
                };
            counters.Add(sPerSecond);

            // 3. counter for counting average time per operation:

            //                 PerformanceCounterType.AverageTimer32

            CounterCreationData averageTime = 
                new CounterCreationData
                {
                    CounterName = string.Format("average time per {0}", name),
                    CounterHelp = string.Format("Average duration per {0} execution", name),
                    CounterType = PerformanceCounterType.AverageTimer32
                };
            counters.Add(averageTime);

            // 4. base counter for counting average time

            //         per operation: PerformanceCounterType.AverageBase

            CounterCreationData averageTimeBase = 
                new CounterCreationData
                {
                    CounterName = string.Format("average time per {0} base", name),
                    CounterHelp = string.Format("Average duration per {0} execution base", name),
                    CounterType = PerformanceCounterType.AverageBase
                };
            counters.Add(averageTimeBase);


        }

        public void TotalGetTimeStart() 
        { 
            TotalGetTime.Start(); 
        }

        public void TotalGetTimeStop() 
        { 
            TotalGetTime.Stop(); 
            Counters[(int)StatsTypesEnum.Get][(int)StatsCounterTypeEnum.AveragePerSec].IncrementBy(TotalGetTime.ElapsedTicks);
            TotalGetTime.Reset();
        }

        public void TotalGetCountIncrement() 
        { 
            Counters[(int)StatsTypesEnum.Get][(int)StatsCounterTypeEnum.Count].Increment();
            Counters[(int)StatsTypesEnum.Get][(int)StatsCounterTypeEnum.CountPerSec].Increment();
        }


        public void TotalSaveTimeStart()
        {
            TotalSaveTime.Start();
        }

        public void TotalSaveTimeStop()
        {
            TotalSaveTime.Stop();
            Counters[(int)StatsTypesEnum.Save][(int)StatsCounterTypeEnum.AveragePerSec].IncrementBy(TotalSaveTime.ElapsedTicks);
            TotalSaveTime.Reset();
        }

        public void TotalSaveCountIncrement()
        {
            Counters[(int)StatsTypesEnum.Save][(int)StatsCounterTypeEnum.Count].Increment();
            Counters[(int)StatsTypesEnum.Save][(int)StatsCounterTypeEnum.CountPerSec].Increment();
        }



        public void TotalPurgeTimeStart()
        {
            TotalPurgeTime.Start();
        }

        public void TotalPurgeTimeStop()
        {
            TotalPurgeTime.Stop();
            Counters[(int)StatsTypesEnum.Purge][(int)StatsCounterTypeEnum.AveragePerSec].IncrementBy(TotalPurgeTime.ElapsedTicks);
            TotalPurgeTime.Reset();
        }

        public void TotalPurgeCountIncrement()
        {
            Counters[(int)StatsTypesEnum.Purge][(int)StatsCounterTypeEnum.Count].Increment();
            Counters[(int)StatsTypesEnum.Purge][(int)StatsCounterTypeEnum.CountPerSec].Increment();
        }

        public void TotalPurgeCountIncrement(int howMuch)
        {
            Counters[(int)StatsTypesEnum.Purge][(int)StatsCounterTypeEnum.Count].Increment();
            Counters[(int)StatsTypesEnum.Purge][(int)StatsCounterTypeEnum.CountPerSec].IncrementBy(howMuch);
        }
    }
}
